/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp;

import java.util.logging.Level;
import java.util.*;
import ssp.agent.*;
import ssp.database.*;
import ssp.event.*;
import ssp.net.*;
import ssp.service.*;
import ssp.strategy.agent.*;
import ssp.strategy.agent.util.PathTable;
import ssp.strategy.factory.*;
import ssp.topology.*;
import ssp.utility.*;

/**
 * yet another simulation
 * 基本的にはデバッグ用
 * @author yamazaki
 */
public class YA_Simulation {
    
    public static void main(String args[]) {
        
        for(int i=0 ; i<PropertyManager.getValueAsInteger("SimulationNum") ; i++) {
            
            preparation();
            
            new PathTableUpdateEvent(0).fire();
            
            updateDatabase();
            
            calcHopCount();
            
            SimulationManager.initAll();
        }
        
    }
    
    private static void preparation() {
        NWcomponentFactory.createNWcomponent(PropertyManager.getValueAsInteger("NWcomponentNum"));
        TopologyMaker.makeWSmodel(PropertyManager.getValueAsInteger("LinkNum"), PropertyManager.getValueAsDouble("LinkProb"));
        NWcomponentManager.getINSTANCE().initAllInternalPathMap();
        NWresourceFactory.allocateNWresource(PropertyManager.getValueAsInteger("NetworkRequirementNum"), PropertyManager.getValueAsInteger("NetworkRequirementRange"), PropertyManager.getValueAsDouble("NetworkRequirementMax"));
        FrontendServerFactory.createFrontendServer(PropertyManager.getValueAsInteger("FrontendServerNum"), PropertyManager.getValueAsDouble("FrontendServerMinCapacity"), PropertyManager.getValueAsDouble("FrontendServerMaxCapacity"));
        FrontendServerFactory.allocateFrontendServer();
        ServiceEntryFactory.createServiceEntry(PropertyManager.getValueAsInteger("ServiceEntryTypeNum"), PropertyManager.getValueAsInteger("ServiceEntryNumOfFrontendServer"), PropertyManager.getValueAsInteger("ServiceRequirementNum"), PropertyManager.getValueAsInteger("ServiceRequirementRange"));
    }
    
    private static void updateDatabase() {
        NetworkMap NWDB = DatabaseManager.getINSTANCE().getNetworkMap();
        for (NWcomponent src : NWcomponentManager.getINSTANCE().getNWcomponentList()) {
            NWDB.updateConnectionTable(0.0, src);
            NWDB.updateHopCountTable(0.0, src);
        }
    }
    
    private static void calcWorkloadAvg() {
        double sum = 0.0;
        ServiceEntryPool pool = ServiceEntryPool.getINSTANCE();
        for (ServiceEntry entry : pool.getServiceEntryList()) {
            sum += entry.getWorkload();
        }
        LoggingManager.logging(Level.INFO, "avg of workload: " + sum / (double)pool.getServiceEntryNum(), new Throwable());
    }
    
    private static void searchMaxWorkload() {
        double maxNum = 0.0;
        for(ServiceEntry entry : ServiceEntryPool.getINSTANCE().getServiceEntryList()) {
            if(entry.getWorkload() > maxNum) {
                maxNum = entry.getWorkload();
            }
        }
        LoggingManager.logging(Level.INFO, "max workload: " + maxNum, new Throwable());
    }
    
    private static void calcHopCount() {
        Map<Integer, Integer> hopCountMap = new TreeMap<>();
        for(int hop : DatabaseManager.getINSTANCE().getNetworkMap().getHopCountTable().values()) {
            if(hopCountMap.containsKey(hop)) {
                hopCountMap.put(hop, hopCountMap.get(hop)+1);
            } else {
                hopCountMap.put(hop, 1);
            }
        }
        for(Map.Entry<Integer, Integer> entry : hopCountMap.entrySet()) {
            LoggingManager.logging(Level.INFO, entry.getKey() + "hop: " + entry.getValue(), new Throwable());
        }
    }
    
}
